package com.ruoyi.common.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.config.AiBaseInfoConfig;
import com.ruoyi.common.config.LlmInfoConfig;
import com.ruoyi.common.utils.file.FileDownloadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.min_io.MinIOUtil;
import com.ruoyi.common.utils.spring.SpringUtils;
import io.minio.errors.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class MinerUUtils {


    public static MinIOUtil getMinIOUtil() {
        return SpringUtils.getBean(MinIOUtil.class);
    }


    /**
     * 通过url 上传文件
     *
     * @param fileUrl 文件url
     * @return 响应结果
     */
    public static String connectionMinerU(String fileUrl) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "Bearer " + AiBaseInfoConfig.getMinerUToken());
        headers.put("Content-Type", "application/json");
        headers.put("Accept", "*/*");

        // 使用Fastjson2构建JSON请求体
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("url", fileUrl);
        jsonObject.put("is_ocr", true);
        jsonObject.put("model_version", "vlm");

        String jsonBody = jsonObject.toString();
        String url = StringUtils.format("{}/api/v4/extract/task", AiBaseInfoConfig.getMinerUUrl());


        ResponseEntity<String> response = RestTemplateClient.post(url, headers, jsonBody);
        return response.getBody();
    }


    /**
     * 上传文件方式调用minerU
     *
     * @param file multipartFile 文件
     * @return 响应结果
     */
    public static String connectionMinerU(MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {

        //将上传的文件存入minio
        Map<String, String> stringStringMap = MinIOUtil.putObject(file, "/temp_upload");
        //获取minio 返回的链接
        String s = stringStringMap.get("fileUrl");
        return connectionMinerU(s);

    }

    /**
     * 获取解析后的结果（需要循环调用）
     *
     * @return
     */

    public static String taskMinerU(String json) throws IOException, InterruptedException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        JSONObject parse;
        try {
            parse = JSONObject.parse(json);
        } catch (Exception e) {
            log.error("文件上传minerU失败", e);
            throw new RuntimeException("文件上传minerU失败");
        }
        String msg = parse.getString("msg");
        if (!"ok".equals(msg)) {
            throw new RuntimeException("minerU 文件解析异常");
        }
        String taskId = parse.getJSONObject("data").getString("task_id");
        boolean success = true;
        while (success) {
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", "Bearer " + AiBaseInfoConfig.getMinerUToken());
            headers.put("Content-Type", "application/json");
            headers.put("Accept", "*/*");

            String url = StringUtils.format("{}/api/v4/extract/task/{}", AiBaseInfoConfig.getMinerUUrl(), taskId);

            //发送查询请求
            ResponseEntity<String> stringResponseEntity = RestTemplateClient.get(url, headers);
            String body = stringResponseEntity.getBody();
            JSONObject bodyJson = JSONObject.parse(body);
            String string = bodyJson.getJSONObject("data").getString("state");
            success = !isFinalStatus(string);
            //成功时候就解析成功
            if ("done".equals(string)) {
                String fillUrl = bodyJson.getJSONObject("data").getString("full_zip_url");
                MultipartFile multipartFile = FileDownloadUtils.downloadFileStream(fillUrl, "");

                File unzip = ZipUtil.unzip(multipartFile.getInputStream(), new File(LlmInfoConfig.getProfile()), null);

                File[] files = unzip.listFiles();
                Map<String, String> imageUrls = new HashMap<>();
                for (File file : files) {
                    if (file.isDirectory()) {
                        File[] images = file.listFiles();
                        for (File image : images) {
                            Map<String, String> stringStringMap = getMinIOUtil().putObject(image, "/temp_upload_image");
                            String s = stringStringMap.get("fileUrl");
                            imageUrls.put("images/" + image.getName(), s);
                        }
                    }
                }
                for (File file : files) {
                    String suffix = FileUtils.getFileExtension(file.getName());
                    if ("md".equals(suffix)) {
                        //替换md文件中的图片路径
                        String updatedMdContent = FileUtil.readUtf8String(file); // 遍历映射，替换所有图片路径
                        for (Map.Entry<String, String> entry : imageUrls.entrySet()) {
                            String oldPath = entry.getKey();
                            String newPath = entry.getValue();

                            // 构造原始的Markdown图片标记和新的图片标记
                            String oldImageTag = "![](" + oldPath + ")";
                            String newImageTag = "![](" + newPath + ")";

                            // 替换内容
                            updatedMdContent = updatedMdContent.replace(oldImageTag, newImageTag);
                        }
                        FileUtils.deleteFolderContentsOnly(LlmInfoConfig.getProfile());
                        // 将更新后的内容写回文件
                        return updatedMdContent;
                    }
                }
            } else {
                Thread.sleep(5000);
            }

        }
        throw new RuntimeException("文件解析失败");
    }

    /**
     * 判断是否为最终状态
     *
     * @param status 任务状态
     * @return 是否为最终状态
     */
    public static boolean isFinalStatus(String status) {
        return "done".equalsIgnoreCase(status) ||
                "failed".equalsIgnoreCase(status);
    }

}
